using System;
using System.Collections.Generic;
using System.IO;
using Sce.PlayStation.Core;
using Sce.PlayStation.Core.Input;

namespace Nyanimals
{
	public class CLoadingState : CBaseState
	{
        public enum LoadType {LoadWorld, LoadRace, LoadError};
        LoadType toLoad;
        int fileType;
        
        public LoadType TypeLoading
        {
            get { return toLoad;}
        }
        
		public CLoadingState (LoadType load)
		{
            toLoad = load;
		}
		
		public void Enter()
		{
            fileType = -1;
		}
		
		public void Exit()
		{
		}
		
		public void Input()
		{
			
		}
		
		public void Update(float deltaTime)
		{
            switch(toLoad)
            {
            case LoadType.LoadWorld:
                LoadLevel("/Application/Resources/Models/SR_TestLevel.SRL");
                break;
            case LoadType.LoadRace:
                LoadLevel("/Application/Resources/Models/SR_TestTrack.SRL");
                break;
            case LoadType.LoadError:
                throw new NotImplementedException();
                break;
                
            }            
            // setup the fonts
            CSimpleFont.Instance.Init();
            
            // determin what state to move to
            if(fileType == 0)
            {
                CStateMachine.Instance.ChangeState(new CWorldState());
            }
            else if(fileType == 1)
            {
                CStateMachine.Instance.ChangeState(new CRaceState());
            }
		}
		
		public void Render()
		{
		}
		
		
		private void LoadLevel(string szFileName)
		{
			BinaryReader read = new BinaryReader(File.Open(szFileName, FileMode.Open, FileAccess.Read));
			
			string header = new string(read.ReadChars(5));
            if( header == "LEVEL")
            {
                fileType = 0;
                LoadWorld(read, szFileName);
            }
            else if( header == "TRACK")
            {
                fileType = 1;
                LoadTrack(read, szFileName);
            }
            
			
		}

		private void LoadWorld(BinaryReader read, string szFileName)
        {
            // read in each mesh
            int nNumMesh = read.ReadInt32();
            
            // prepare the mesh file location to open
            string meshName = szFileName;
            int loc = szFileName.LastIndexOf('/');
            
            meshName = meshName.Remove(loc + 1);
            
            for(int nMeshCount = 0; nMeshCount < nNumMesh; ++nMeshCount)
            {
             int nameLength = read.ReadInt32();
             char[] szMeshName = new char[nameLength];
             szMeshName = read.ReadChars(nameLength);
             
             // build the file name
             string stringMeshName = new string(szMeshName) + ".SRM";
            
             int nNumTransforms = read.ReadInt32();
            
             for(int transformIndex = 0; transformIndex < nNumTransforms; ++transformIndex)
             {
                 // load the transform
                 // LevelContext spawn;
                 // spawn.nEncounter = read.ReadInt32();
                 // spawn.matrix = read.ReadSingle;
                 int nEncounter = read.ReadInt32();
                 Matrix4 mat = new Matrix4( read.ReadSingle(), read.ReadSingle(), read.ReadSingle(), read.ReadSingle(), 
                                           read.ReadSingle(), read.ReadSingle(), read.ReadSingle(), read.ReadSingle(), 
                                           read.ReadSingle(), read.ReadSingle(), read.ReadSingle(), read.ReadSingle(), 
                                           read.ReadSingle(), read.ReadSingle(), read.ReadSingle(), read.ReadSingle());
            
                 // add the mesh
                 CContextManager.Instance.AddStaticContext(CMeshManager.Instance.LoadMesh(stringMeshName), mat);
             }
            }
            read.Close();
            read.Dispose();
            // TODO: Finish Loading in everything
            /*
         //m_bDoneLevelRead = true;
     
         // ground transform
         D3DXMATRIX Groundmat;
         D3DXMATRIX Groundmat2;
         in.read((char*)&Groundmat, sizeof(D3DXMATRIX));
     
         memcpy(&Groundmat2, &Groundmat, sizeof(D3DXMATRIX));
         D3DXMatrixIdentity(&Groundmat);
     
         //CStaticContext* pColGround = m_pRenderer->AddStaticContext("Environments/Candy Town/Ground_Collision.SRM", "Environments/Skybox/Skybox_Texture.tga", NULL, NULL, Groundmat, false, true);
     
         //CMesh *mesh  = m_pRenderer->getContextManager()->getMeshManager()->GetMesh(pColGround->GetMeshIndex());
     
         // load in the ground colision
         unsigned int nNumGroundVerts = 0;
         in.read((char*)&nNumGroundVerts, sizeof(unsigned int));
     
         m_pObjMan->m_vGroundVerts.resize(nNumGroundVerts);
         in.read((char*)&m_pObjMan->m_vGroundVerts[0], sizeof(Collision_Vertex) * nNumGroundVerts);
     
         unsigned int nNumGroundTris = 0;
         in.read((char*)&nNumGroundTris, sizeof(unsigned int));
     
         m_pObjMan->m_vGroundTriangles.resize(nNumGroundTris);
         in.read((char*)&m_pObjMan->m_vGroundTriangles[0], sizeof(tTriangle) * nNumGroundTris);
     
     #if COLLISION
         EnterCriticalSection(&CS_Rendering);
         m_pRenderer->AddCollisionMesh(m_pObjMan->m_vGroundTriangles, m_pObjMan->m_vGroundVerts);
         LeaveCriticalSection(&CS_Rendering);
     #endif
         // load in the collision walls
         int numCollisionWalls = 0;
         in.read((char*)&numCollisionWalls, sizeof(int));
     
         //EnterCriticalSection(&CS_Rendering);
         m_pObjMan->m_vCollision.resize(numCollisionWalls);
         //LeaveCriticalSection(&CS_Rendering);
     
         for(int wallIndex = 0; wallIndex < numCollisionWalls; ++wallIndex)
         {
             CObjectManager::CollisionData &wall = m_pObjMan->m_vCollision[wallIndex];
     
             int nNumCollisionVerts = 0;
             in.read((char*)&nNumCollisionVerts, sizeof(int));
     
             wall.m_vVerts.resize(nNumCollisionVerts);
             in.read((char*)&wall.m_vVerts[0], sizeof(Collision_Vertex) * nNumCollisionVerts);
     
             int nNumCollisionTris = 0;
             in.read((char*)&nNumCollisionTris, sizeof(int));
     
             wall.m_vTriangles.resize(nNumCollisionTris);
             in.read((char*)&wall.m_vTriangles[0], sizeof(tTriangle) * nNumCollisionTris);
             in.read((char*)&wall.mat, sizeof(D3DXMATRIX));
         }
     
     
         // load the spawn points
         unsigned int nNumSpawn = 0;
         in.read((char*)&nNumSpawn, sizeof(unsigned int));
     
         for(unsigned int spawnCount = 0; spawnCount < nNumSpawn; ++spawnCount)
         {
             // read in the name size
             unsigned int nSpawnName = 0;
             SPAWN_TYPES spawnType = TOTAL_SPAWN;
             in.read((char*)&nSpawnName, sizeof(unsigned int));
     
             // read in the name of the current spawntype
             std::string szSpawnName;
             szSpawnName.resize(nSpawnName);
             in.read((char*)&szSpawnName.at(0), nSpawnName);
     
             // detemine what the type of the spawn is
             if(szSpawnName.find("dot") != std::string::npos)
             {
                 spawnType = DOT_SPAWN;
             }
             else if(szSpawnName.find("carrot") != std::string::npos)
             {
                 spawnType = CARROT_SPAWN;
             }
             else if(szSpawnName.find("tomato") != std::string::npos)
             {
                 spawnType = TOMATO_SPAWN;
             }
             else if(szSpawnName.find("melee") != std::string::npos)
             {
                 spawnType = MELEE_SPAWN;
             }
             else if(szSpawnName.find("ranged") != std::string::npos)
             {
                 spawnType = RANGED_SPAWN;
             }
             else if(szSpawnName.find("boss") != std::string::npos)
             {
                 spawnType = BOSS_SPAWN;
             }
             else if(szSpawnName.find("trigger") != std::string::npos)
             {
                 spawnType = TRIGGER_SPAWN;
             }
             else
             {
                 MessageBox(0, string("Error Spawn Type: " + szSpawnName).c_str(), "Error", MB_OK);
             }
     
             // read in all the spawn locationms and encounter IDs
             unsigned int nSpawnCount = 0;
             in.read((char*)&nSpawnCount, sizeof(unsigned int));
             m_SpawnPoints_Raw[szSpawnName].resize(nSpawnCount);
             for(unsigned int nSpawnIndex = 0; nSpawnIndex < nSpawnCount; ++nSpawnIndex)
             {
                 SpawnPoint spawn;
                 spawn.type = spawnType;
                 in.read((char*)&spawn.nEncounter, sizeof(int));
                 in.read((char*)&spawn.matrix, sizeof(D3DXMATRIX));
     
                 // put hte raw spawn data here
                 m_SpawnPoints_Raw[szSpawnName].at(nSpawnIndex) = spawn;
     
                 // queue the spawn points to be placed
                 EnterCriticalSection(&CS_SpawnContexts);
                 m_SpawnPoints.push(spawn);
                 LeaveCriticalSection(&CS_SpawnContexts);
             }
     
     
     
         }
         m_bDoneSpawnRead = true;
     
         // load the barriers
         unsigned int nNumBarrier = 0;
         in.read((char*)&nNumBarrier, sizeof(unsigned int));
     
         m_pObjMan->m_vBarrierCollision.resize(nNumBarrier);
     
         for(unsigned int barrierCount = 0; barrierCount < nNumBarrier; ++barrierCount)
         {
             CObjectManager::CollisionData &bar = m_pObjMan->m_vBarrierCollision[barrierCount];
     
             int nNumCollisionVerts = 0;
             in.read((char*)&nNumCollisionVerts, sizeof(int));
     
             bar.m_vVerts.resize(nNumCollisionVerts);
             in.read((char*)&bar.m_vVerts[0], sizeof(Collision_Vertex) * nNumCollisionVerts);
     
             int nNumCollisionTris = 0;
             in.read((char*)&nNumCollisionTris, sizeof(int));
     
             bar.m_vTriangles.resize(nNumCollisionTris);
             in.read((char*)&bar.m_vTriangles[0], sizeof(tTriangle) * nNumCollisionTris);
             in.read((char*)&bar.mat, sizeof(D3DXMATRIX));
     
         }
     
         // load in the areas
         unsigned int nNumArea = 0;
         in.read((char*)&nNumArea, sizeof(unsigned int));
         m_Area.resize(nNumArea);
     
         for(unsigned int areaIndex = 0; areaIndex < nNumArea; ++areaIndex)
         {
             in.read((char*)&m_Area[areaIndex], sizeof(tArea));
         }
     
         in.close();
         in.clear();
         */
        }
        private void LoadTrack(BinaryReader read, string szFileName)
        {
            LoadWorld(read, szFileName);
        }
        
		public StateTypes GetStateType()
		{
			return StateTypes.Loading_State;
		}
	}
}

